﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using System.IO;
using DH.Core;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Authentication.Cookies;
using NLog.Web;
using Microsoft.Extensions.Logging;
using NLog.Extensions.Logging;
using DH.Data;
using Microsoft.EntityFrameworkCore;
using DH.Data.ORM.EF;
using DH.Service;
using DH.Service.Domain.User;
using DH.Core.Exceptions;
using Microsoft.Extensions.DependencyInjection.Extensions;
using DH.Core.Helper;
using DH.Core.MapperEx.DataContractMapper;
using DH.Core.MapperHelper;
using AutoMapper;
using DH.Entity;
using DH.Web.MVC.ViewModels;
using CacheManager.Core;
using Microsoft.AspNetCore.Mvc.Razor;
using System.Globalization;
using Microsoft.Extensions.Options;
using System.Text;

namespace DH.Web.MVC
{
    public class Startup
    {
        IHostingEnvironment _env;
        public Startup(IHostingEnvironment env)
        {
            this._env = env;

            var builder = new Microsoft.Extensions.Configuration.ConfigurationBuilder()
                      .SetBasePath(env.ContentRootPath)
                      .AddJsonFile(Path.Combine("config", "appsettings.json"), optional: true, reloadOnChange: true)  // Settings for the application
                      .AddJsonFile(Path.Combine("config", $"appsettings.{env.EnvironmentName}.json"), optional: true, reloadOnChange: true)                      
                      .AddJsonFile(Path.Combine("config", "cache.json"), optional: false)
                      .AddEnvironmentVariables();                                              // override settings with environment variables set in compose.   

            //重新配置config
            Configuration = builder.Build();

            //保持到Global
            Global.Configuration = Configuration;

        }

        public IConfigurationRoot Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
           
            services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
            services.AddLocalization(options => options.ResourcesPath = "Resources");

            ///todo: 根据orm,选择注入dbcontext,repository 待完成
            //根据orm,选择注入dbcontext,repository
            //如果使用EF,注册dbContext
            var connStr = DbHelper.DbConnectionString;
            services.AddDbContext<DHDbContext>(options=>options.UseSqlServer(connStr) );

            services.AddTransient(typeof(IEFCoreQueryableRepository<>), typeof(EFCoreBaseRepository<>));
            services.AddTransient(typeof(IEFCoreQueryableRepository<,>), typeof(EFCoreBaseRepository<,>));

            //工作单元
            services.AddScoped<DbCoreUnitOfWork>();

            //注册异常服务
            services.TryAddScoped<IExceptionMapper, BaseExceptionMapper>();

            //把ServiceCollection注入
            services.AddSingleton(typeof(IServiceCollection), (o) => { return services; });

            //扫描所有模块注册以下接口所有继承类
            //services.Scan(scan => scan
            //    .FromAssemblies(AssemblyHelper.LoadCompileAssemblies())                
            //    .AddClasses(classes => classes.AssignableTo(typeof(ICrudDtoMapper<,,>)))
            //    .AsImplementedInterfaces()
            //    .WithTransientLifetime()
            //    );

            //数据映射
            services.AddTransient(typeof(ICrudDtoMapper<,,>),typeof(BaseCrudDtoMapper<,,>));

            //注入业务服务
            services.Inject();

            //services.AddMemoryCache();
            services.AddSession();



            //用户认证
            //services.AddIdentity<UserEntity, RoleEntity>();
            services.AddAuthentication(options =>
            {
                options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
            })
            .AddCookie(o => o.LoginPath = new PathString("/Account/Login"));

            //语言本地化
            services.AddLocalization(options=>options.ResourcesPath="Resources");
            services.AddMvc(options =>
            {
                //options.Filters.Add(typeof(HttpGlobalExceptionFilter));
            })
            .AddControllersAsServices()
            .AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix)
            .AddDataAnnotationsLocalization();
            services.Configure<RequestLocalizationOptions>(opts=> {
                var supportedCultures = new List<CultureInfo>
                  {
                    new CultureInfo("en-US"),
                    new CultureInfo("zh-CN")
                  };
                opts.SupportedCultures = supportedCultures;
                opts.SupportedUICultures = supportedCultures;

            });


            #region 缓存            

            //services.AddSingleton(typeof(ICacheManager<>), typeof(BaseCacheManager<>));

            //services.AddCacheManagerConfiguration(Configuration, cfg => cfg.WithMicrosoftLogging(services));

            //services.AddCacheManager();
            #endregion
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
        {

            //Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);//这是为了防止中文乱码
            loggerFactory.AddConsole(Configuration.GetSection("Logging"));
            loggerFactory.AddDebug();
            /* NLog */
            loggerFactory.AddNLog();
            this._env.ConfigureNLog(Path.Combine("config", "nlog.config"));

            app.AddNLogWeb();

            Global.ServiceProvider = app.ApplicationServices;

            /* 初始化 AutoMapper */
            ///配置
            DHMapper.InitializeMap();



            //if (env.IsDevelopment())
            //{
            //    app.UseDeveloperExceptionPage();
            //    app.UseBrowserLink();
            //}
            //else
            //{
            //    app.UseExceptionHandler("/Home/Error");
            //}

            //自定义错误页面
            //app.UseExceptionHandler(errorApp =>
            //{
            //    errorApp.Run(async context =>
            //    {
            //        context.Response.StatusCode = 500;
            //        if (context.Request.Headers["X-Requested-With"] != "XMLHttpRequest")
            //        {
            //            context.Response.ContentType = "text/html";
            //            await context.Response.SendFileAsync($@"{env.WebRootPath}/errors/500.html");
            //        }
            //    });
            //});
            //app.UseStatusCodePagesWithReExecute("/Error/errors/{0}");


            app.UseStaticFiles();
            app.UseAuthentication();
            app.UseSession();

            var requestLocalizationOptions = app.ApplicationServices.GetService<IOptions<RequestLocalizationOptions>>().Value;
            app.UseRequestLocalization(requestLocalizationOptions);

            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "area",
                    template: "{area:exists}/{controller=Home}/{action=Index}/{id?}");

                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}");
            });
        }
    }
}
